package com.apigen.platform.service.impl;

import com.apigen.platform.dto.LoginRequest;
import com.apigen.platform.dto.LoginResponse;
import com.apigen.platform.entity.SysUser;
import com.apigen.platform.mapper.SysUserMapper;
import com.apigen.platform.service.IAuthService;
import com.apigen.platform.service.ICaptchaService;
import com.apigen.platform.util.JwtUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 *
 * @author API Generator Platform
 * @since 2025-09-24
 */
@Slf4j
@Service
public class AuthServiceImpl implements IAuthService {

    private final SysUserMapper userMapper;
    private final JwtUtil jwtUtil;
    private final BCryptPasswordEncoder passwordEncoder;
    private final ICaptchaService captchaService;
    
    @Autowired(required = false)
    private RedisTemplate<String, Object> redisTemplate;

    public AuthServiceImpl(SysUserMapper userMapper, JwtUtil jwtUtil, BCryptPasswordEncoder passwordEncoder, ICaptchaService captchaService) {
        this.userMapper = userMapper;
        this.jwtUtil = jwtUtil;
        this.passwordEncoder = passwordEncoder;
        this.captchaService = captchaService;
    }

    private static final String USER_TOKEN_PREFIX = "user:token:";
    private static final String USER_INFO_PREFIX = "user:info:";

    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        // 1. 验证验证码（如果提供了验证码）
        if (loginRequest.getCaptchaKey() != null && loginRequest.getCaptcha() != null) {
            boolean captchaValid = captchaService.validateCaptcha(loginRequest.getCaptchaKey(), loginRequest.getCaptcha());
            if (!captchaValid) {
                throw new RuntimeException("验证码错误或已过期");
            }
        }
        
        // 2. 验证用户是否存在
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getAccountName, loginRequest.getAccountName())
                   .eq(SysUser::getDeleted, false);
        
        SysUser user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 3. 验证用户是否启用
        if (!user.getIsEnabled()) {
            throw new RuntimeException("用户已被禁用");
        }

        // 4. 验证密码
        log.debug("=== 密码验证调试信息 ===");
        log.debug("用户账号: {}", loginRequest.getAccountName());
        log.debug("前端传入的明文密码: {}", loginRequest.getPassword());
        log.debug("数据库中的密码哈希: {}", user.getUserPassword());
        log.debug("密码哈希长度: {}", user.getUserPassword() != null ? user.getUserPassword().length() : "null");
        
        boolean passwordMatches = passwordEncoder.matches(loginRequest.getPassword(), user.getUserPassword());
        log.debug("密码匹配结果: {}", passwordMatches);
        
        // 生成一个新的哈希用于测试
        if (!passwordMatches) {
            String newHash = passwordEncoder.encode(loginRequest.getPassword());
            log.debug("如果要更新数据库，使用此哈希: {}", newHash);
            boolean testMatch = passwordEncoder.matches(loginRequest.getPassword(), newHash);
            log.debug("新生成哈希的验证结果: {}", testMatch);
            
            // 测试常见密码
            String[] commonPasswords = {"123456", "admin", "password", "123123", "admin123", "12345678"};
            log.debug("测试数据库哈希与常见密码的匹配:");
            for (String testPassword : commonPasswords) {
                boolean matches = passwordEncoder.matches(testPassword, user.getUserPassword());
                log.debug("密码 '{}' 与数据库哈希匹配: {}", testPassword, matches);
                if (matches) {
                    log.info("*** 找到正确密码: {} ***", testPassword);
                    break;
                }
            }
        }
        log.debug("========================");
        
        if (!passwordMatches) {
            log.error("密码验证失败 - 账号: {}, 输入密码: {}, 数据库哈希: {}", 
                loginRequest.getAccountName(), loginRequest.getPassword(), user.getUserPassword());
            throw new RuntimeException("密码错误");
        }

        // 5. 更新登录信息
        user.setLastLoginTime(LocalDateTime.now());
        user.setLoginCount(user.getLoginCount() + 1);
        userMapper.updateById(user);

        // 6. 生成Token
        String accessToken = jwtUtil.generateAccessToken(user.getUserId(), user.getAccountName(), user.getIsAdmin());
        String refreshToken = jwtUtil.generateRefreshToken(user.getUserId(), user.getAccountName());

        // 7. 缓存用户Token
        if (redisTemplate != null) {
            String tokenKey = USER_TOKEN_PREFIX + user.getUserId();
            redisTemplate.opsForValue().set(tokenKey, accessToken, 2, TimeUnit.HOURS);
        }

        // 7. 构建用户信息
        LoginResponse.UserInfo userInfo = LoginResponse.UserInfo.builder()
                .userId(user.getUserId())
                .accountName(user.getAccountName())
                .nickName(user.getNickName())
                .avatar(user.getAvatar())
                .email(user.getEmail())
                .phone(user.getPhone())
                .isAdmin(user.getIsAdmin())
                .lastLoginTime(user.getLastLoginTime())
                .roles(new ArrayList<>()) // TODO: 从角色表查询
                .permissions(new ArrayList<>()) // TODO: 从权限表查询
                .build();

        // 8. 缓存用户信息
        if (redisTemplate != null) {
            String userInfoKey = USER_INFO_PREFIX + user.getUserId();
            redisTemplate.opsForValue().set(userInfoKey, userInfo, 2, TimeUnit.HOURS);
        }

        log.info("用户 {} 登录成功", user.getAccountName());

        return LoginResponse.builder()
                .accessToken(accessToken)
                .refreshToken(refreshToken)
                .tokenType("Bearer")
                .expiresIn(7200L) // 2小时
                .userInfo(userInfo)
                .build();
    }

    @Override
    public LoginResponse refreshToken(String refreshToken) {
        // 1. 验证刷新令牌
        if (!jwtUtil.validateRefreshToken(refreshToken)) {
            throw new RuntimeException("刷新令牌无效或已过期");
        }

        // 2. 从刷新令牌中获取用户信息
        Long userId = jwtUtil.getUserIdFromToken(refreshToken);
        String accountName = jwtUtil.getAccountNameFromToken(refreshToken);

        // 3. 查询用户信息
        SysUser user = userMapper.selectById(userId);
        if (user == null || !user.getIsEnabled()) {
            throw new RuntimeException("用户不存在或已被禁用");
        }

        // 4. 生成新的访问令牌
        String newAccessToken = jwtUtil.generateAccessToken(userId, accountName, user.getIsAdmin());

        // 5. 更新缓存
        if (redisTemplate != null) {
            String tokenKey = USER_TOKEN_PREFIX + userId;
            redisTemplate.opsForValue().set(tokenKey, newAccessToken, 2, TimeUnit.HOURS);
        }

        return LoginResponse.builder()
                .accessToken(newAccessToken)
                .refreshToken(refreshToken) // 刷新令牌保持不变
                .tokenType("Bearer")
                .expiresIn(7200L)
                .build();
    }

    @Override
    public void logout(Long userId) {
        // 清除Redis中的用户Token和信息
        if (redisTemplate != null) {
            String tokenKey = USER_TOKEN_PREFIX + userId;
            String userInfoKey = USER_INFO_PREFIX + userId;
            
            redisTemplate.delete(tokenKey);
            redisTemplate.delete(userInfoKey);
        }
        
        log.info("用户 {} 退出登录", userId);
    }

    @Override
    public LoginResponse.UserInfo getCurrentUserInfo(Long userId) {
        // 先从缓存获取
        LoginResponse.UserInfo cachedUserInfo = null;
        if (redisTemplate != null) {
            String userInfoKey = USER_INFO_PREFIX + userId;
            cachedUserInfo = (LoginResponse.UserInfo) redisTemplate.opsForValue().get(userInfoKey);
            
            if (cachedUserInfo != null) {
                return cachedUserInfo;
            }
        }

        // 缓存未命中，从数据库查询
        SysUser user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        LoginResponse.UserInfo userInfo = LoginResponse.UserInfo.builder()
                .userId(user.getUserId())
                .accountName(user.getAccountName())
                .nickName(user.getNickName())
                .avatar(user.getAvatar())
                .email(user.getEmail())
                .phone(user.getPhone())
                .isAdmin(user.getIsAdmin())
                .lastLoginTime(user.getLastLoginTime())
                .roles(new ArrayList<>()) // TODO: 从角色表查询
                .permissions(new ArrayList<>()) // TODO: 从权限表查询
                .build();

        // 更新缓存
        if (redisTemplate != null) {
            String userInfoKey = USER_INFO_PREFIX + userId;
            redisTemplate.opsForValue().set(userInfoKey, userInfo, 2, TimeUnit.HOURS);
        }

        return userInfo;
    }
}

